﻿using Sgr.Utilities;

namespace Sgr.Licence.Services
{
    /// <summary>
    /// 激活码生成器
    /// </summary>
    public class ActivationCodeGenerator : IActivationCodeGenerator
    {
        #region 公共方法

        /// <summary>
        /// 生成激活码
        /// </summary>
        /// <param name="registrationCode">注册码</param>
        /// <param name="numOfLic">授权数量</param>
        /// <param name="startTime">授权开始时间</param>
        /// <param name="endTime">授权结束时间</param>
        /// <returns>加密后的激活码</returns>
        /// <exception cref="ArgumentNullException">参数为空时抛出</exception>
        /// <exception cref="ArgumentException">参数无效时抛出</exception>
        public string GenerateActivationCode(
            string registrationCode,
            long numOfLic,
            DateTime startTime,
            DateTime endTime)
        {
            startTime = startTime.EnsureUtc();
            endTime = endTime.EnsureUtc();

            ValidateParameters(registrationCode, numOfLic, startTime, endTime);

            var plainText = BuildActivationCodePlainText(registrationCode, numOfLic, startTime, endTime);
            var cipherText = EncryptionHelper.Encrypt(plainText, false);

            return LicenseHelper.AppendChecksum(cipherText);
        }

        /// <summary>
        /// 验证激活码是否有效
        /// </summary>
        /// <param name="registrationCode">注册码</param>
        /// <param name="activationCode">激活码</param>
        /// <returns>验证结果，包含验证状态、消息和激活信息</returns>
        public (bool IsValid, string Message, ActivationInfo? Info) ValidateActivationCode(
            string registrationCode,
            string activationCode)
        {
            if (string.IsNullOrEmpty(registrationCode) || string.IsNullOrEmpty(activationCode))
                return (false, "注册码或激活码不能为空", null);

            try
            {
                if (!LicenseHelper.VerifyChecksum(activationCode))
                    return (false, "激活码校验和错误", null);

                var actualCode = LicenseHelper.RemoveChecksum(activationCode);
                var decrypted = EncryptionHelper.Decrypt(actualCode, false);
                var parts = decrypted.Split(LicenseConstants.FieldSeparator);

                if (!IsValidActivationCodeFormat(parts))
                    return (false, "激活码格式错误", null);

                var info = CreateActivationInfo(parts);
                return LicenseHelper.ValidateActivationInfo(info, registrationCode);
            }
            catch (Exception ex)
            {
                return (false, $"激活码验证失败: {ex.Message}", null);
            }
        }

        #endregion 公共方法

        #region 私有辅助方法

        /// <summary>
        /// 验证输入参数
        /// </summary>
        private static void ValidateParameters(
            string registrationCode,
            long numOfLic,
            DateTime startTime,
            DateTime endTime)
        {
            if (string.IsNullOrWhiteSpace(registrationCode))
                throw new ArgumentNullException(nameof(registrationCode));

            if (numOfLic <= 0)
                throw new ArgumentException("授权数量必须大于0", nameof(numOfLic));

            if (startTime >= endTime)
                throw new ArgumentException("结束时间必须晚于开始时间");

            if (startTime < LicenseConstants.BenchmarkDate)
                throw new ArgumentException("开始时间不能早于基准时间", nameof(startTime));
        }

        /// <summary>
        /// 构建激活码明文
        /// </summary>
        private static string BuildActivationCodePlainText(
            string registrationCode,
            long numOfLic,
            DateTime startTime,
            DateTime endTime)
        {
            // 确保开始时间为当天的开始（00:00:00）
            var normalizedStartTime = startTime.Date;
            // 确保结束时间为当天的结束（23:59:59）
            var normalizedEndTime = endTime.Date.AddDays(1).AddTicks(-1);

            var startTicks = LicenseHelper.ConvertToTimestamp(normalizedStartTime);
            var endTicks = LicenseHelper.ConvertToTimestamp(normalizedEndTime);

            return string.Join(LicenseConstants.FieldSeparator,
                registrationCode,
                numOfLic,
                LicenseConstants.Version,
                startTicks,
                endTicks);
        }

        /// <summary>
        /// 验证激活码格式
        /// </summary>
        private static bool IsValidActivationCodeFormat(string[] parts)
        {
            if (parts.Length != LicenseConstants.FieldCount)
                return false;

            return !string.IsNullOrEmpty(parts[0]) && // 注册码
                   long.TryParse(parts[1], out var numLic) && numLic > 0 && // 授权数量
                   !string.IsNullOrEmpty(parts[2]) && // 版本号
                   long.TryParse(parts[3], out _) && // 开始时间
                   long.TryParse(parts[4], out _);   // 结束时间
        }

        /// <summary>
        /// 创建激活信息实例
        /// </summary>
        private static ActivationInfo CreateActivationInfo(string[] parts)
        {
            return new ActivationInfo
            {
                RegistrationCode = parts[0],
                NumOfLic = long.Parse(parts[1]),
                StartTime = LicenseHelper.ParseDateTime(parts[3]),
                EndTime = LicenseHelper.ParseDateTime(parts[4])
            };
        }

        #endregion 私有辅助方法
    }
}